package com.leosam.tvbox.mv.proxy;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.leosam.tvbox.mv.utils.StringUtils;

/**
 * 黑名单文件
 */
public class BlockList {
    private static final String NAME_ADS_LIST = "ads.list";

    private final Logger logger = LoggerFactory.getLogger(BlockList.class);

    /**
     * URL前缀匹配
     */
    public List<String> startsUrl;

    /**
     * URL精确匹配
     */
    public Set<String> equalsUrl;

    /**
     * md5判断(文件大小->md5s)
     */
    public Map<Long, List<byte[]>> hashMatch;

    /**
     * 给定m3u8File的位置,加载该文件所处目录和上级目录的ads.list文件
     * 
     * @param indexM3u8File
     */
    public BlockList(File indexM3u8File) {
        File parentFile = indexM3u8File.getParentFile();
        File subFile = new File(parentFile, NAME_ADS_LIST);
        File parFile = new File(parentFile.getParentFile(), NAME_ADS_LIST);
        load(subFile);
        load(parFile);
    }

    private void load(File file) {
        if (file != null && file.exists()) {
            Pattern pattern = Pattern.compile("(\\d+),([A-Fa-f0-9]{32})");
            try (Scanner scanner = new Scanner(new FileInputStream(file))) {
                while (scanner.hasNextLine()) {
                    String line = scanner.nextLine().trim();
                    if (line.isEmpty()) {
                        continue;
                    }
                    if (line.startsWith("http")) {
                        if (StringUtils.endsWithUrl(line, ".ts")) {
                            if (equalsUrl == null) {
                                equalsUrl = new HashSet<>();
                            }
                            equalsUrl.add(line);
                        } else {
                            if (startsUrl == null) {
                                startsUrl = new ArrayList<>();
                            }
                            startsUrl.add(line);
                        }
                    } else {
                        Matcher matcher = pattern.matcher(line);
                        if (matcher.matches()) {
                            Long size = Long.parseLong(matcher.group(1));
                            String md5 = matcher.group(2).toLowerCase();

                            if (hashMatch == null) {
                                hashMatch = new HashMap<>();
                            }
                            List<byte[]> list = hashMatch.get(size);
                            if (list == null) {
                                list = new ArrayList<>();
                                hashMatch.put(size, list);
                            }
                            list.add(StringUtils.hexStringToByteArray(md5));
                        }
                    }
                }
            } catch (IOException ioe) {
                logger.error("load ads file failed", ioe);
            }
        }
    }

    public boolean isBlockUrl(String url) {
        if (StringUtils.isEmpty(url) || equalsUrl != null && equalsUrl.contains(url)) {
            return true;
        }
        if (startsUrl != null) {
            for (String s : startsUrl) {
                if (url.startsWith(s))
                    return true;
            }
        }
        return false;
    }

    public boolean isBlockFile(File tmpFile) {
        if (hashMatch == null) {
            return false;
        }
        if (tmpFile == null || !tmpFile.exists()) {
            return true;
        }
        long fileLength = tmpFile.length();
        List<byte[]> list = hashMatch.get(fileLength);
        if (list == null) {
            return false;
        }
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            try (FileInputStream fis = new FileInputStream(tmpFile)) {
                byte[] dataBytes = new byte[4096];

                int bytesRead;
                while ((bytesRead = fis.read(dataBytes)) != -1) {
                    md.update(dataBytes, 0, bytesRead);
                }

                byte[] mdBytes = md.digest();
                for (byte[] bs : list) {
                    if (Arrays.equals(mdBytes, bs)) {
                        return true;
                    }
                }
            }
            return false;
        } catch (Exception e) {
            return true;
        }
    }

    /**
     * 判断是否有需要block的url
     * 
     * @return 如果有需要block的url,返回true
     */
    public boolean hasBlockUrl() {
        return (equalsUrl != null && !equalsUrl.isEmpty()) || (startsUrl != null && !startsUrl.isEmpty());
    }

    /**
     * 判断是否有需要block的文件
     * 
     * @return 如果有需要block的文件,则返回true
     */
    public boolean hasBlockFile() {
        return hashMatch != null && !hashMatch.isEmpty();
    }

}
